/*
守护进程
    在程序后台执行的进程，不依赖终端，类似于win中的服务

1、创建子进程，退出父进程。
2、在子进程中调用setsid()创建新的会话，是子进程成为新的会话首进程，并脱离终端控制
3、将当前工作目录更改为根目录，以防占用挂载点。chdir()
4、重设文件权限掩码，以避免继承父进程的权限掩码。umask
5、关闭不再需要的文件描述符(如标准输入、输出、错误)。
6、守护进程进入一个无限循环，执行预定的任务
*/

/*
函数介绍

#include <unistd.h>
pid_t setsid(void);

功能：
    创建一个新会话并使调用进程成为新会话的首领，同时与控制终端分离；

参数：
    无。

返回值：
    成功：返回新会话的会话 ID
    失败：返回-1，并设置相应的错误码。

==================================================================================

#include <unistd.h>
int chdir(const char *path);

功能：
    改变当前工作目录到指定路径。

参数：
    path:指向新的工作目录的路径

返回值：
    成功：返回0.
    失败：返回-1，并设置相应的错误码。
*/


#include "head.h"

int main(int argc,const char *argv[])
{
    //1.创建子进程，退出父进程。
    pid_t pid=0;

    if(-1 == (pid = fork()))
    {
        perror("fork error");
        return 0;
    }

    else if(0<pid)//退出父进程
    {
        exit(1);
    }

    //2.创建新会话
    if(-1==setsid())
    {
        perror("setsid error");
        return 0;
    }

    //3.将当前工作目录更改为根目录
    if(-1==chdir("/"))
    {
        perror("chdir error");
        return 0;
    }

    //4.重设文件权限掩码
    umask(0);

    //5.关闭文件描述符
    fclose(stdout);
    fclose(stdin);
    fclose(stderr);

    //守护进程任务 写死循环
    while(1)
    {
        FILE *fp = fopen("/home/student/系统编程/系统编程/day02/HQYJ.txt","a");//只打开一次文件
        if(fp == NULL)//打开文件失败处理
        {
            perror("fopen error");
            return 0;
        }
        time_t t1 = time(NULL);
        struct tm  *tm_str;

        //进入无限循环，周期性的执行任务
        while(1)
        {
            t1 = time(NULL);//获取时间
            tm_str = localtime(&t1);//将获取的时间转化为本地时间

            //将时间格式化并写入日志文件
            fprintf(fp,"HQYJ_log : %02d-%02d-%02d\n",
            tm_str->tm_hour,tm_str->tm_min,tm_str->tm_sec);
            fflush(fp);//强制刷新缓冲区，将内容写进文件

            sleep(10);//暂停10s，再次记录日志
        }
        fclose(fp);//关闭文件
    }
    return 0;
}